#include <ffs.h>

static UINT8 ffsMsbTbl [256] =	
    {
    0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    };

static UINT8 ffsLsbTbl [256] = 
    {
    0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    };


int ffs32Msb(UINT32 i)
{
    union {
        UINT32 dword;
        UINT16 word[2];
        UINT8 byte[4];
    } i_u;

    i_u.dword = i;

#if (__BYTE_ORDER == __BIG_ENDIAN)

    if (i_u.word[0])
    {
        if (i_u.byte[0])
            return (ffsMsbTbl[i_u.byte[0]] + 24 + 1);
        else
            return (ffsMsbTbl[i_u.byte[1]] + 16 + 1);
    }
    else
    {
        if (i_u.byte[2])
            return (ffsMsbTbl[i_u.byte[2]] + 8 + 1);
        else
            return (ffsMsbTbl[i_u.byte[3]] + (i ? 1 : 0));
    }

#else

    if (i_u.word[1])
    {
        if (i_u.byte[3])
            return (ffsMsbTbl[i_u.byte[3]] + 24 + 1);
        else
            return (ffsMsbTbl[i_u.byte[2]] + 16 + 1);
    }
    else
    {
        if (i_u.byte[1])
            return (ffsMsbTbl[i_u.byte[1]] + 8 + 1);
        else
            return (ffsMsbTbl[i_u.byte[0]] + (i ? 1 : 0));
    }

#endif
}

int ffs32Lsb(UINT32 i)
{
    union {
        UINT32 dword;
        UINT16 word[2];
        UINT8 byte[4];
    } i_u;

    i_u.dword = i;

#if (__BYTE_ORDER == __BIG_ENDIAN)

    if (i_u.word[1])
    {
        if (i_u.byte[3])
            return (ffsLsbTbl[i_u.byte[3]] + 1);
        else
            return (ffsLsbTbl[i_u.byte[2]] + 8 + 1);
    }
    else
    {
        if (i_u.byte[1])
            return (ffsLsbTbl[i_u.byte[1]] + 16 + 1);
        else
            return (ffsLsbTbl[i_u.byte[0]] + (i ? 24 + 1 : 0));
    }

#else

    if (i_u.word[0])
    {
        if (i_u.byte[0])
            return (ffsLsbTbl[i_u.byte[0]] + 1);
        else
            return (ffsLsbTbl[i_u.byte[1]] + 8 + 1);
    }
    else
    {
        if (i_u.byte[2])
            return (ffsLsbTbl[i_u.byte[2]] + 16 + 1);
        else
            return (ffsLsbTbl[i_u.byte[3]] + (i ? 24 + 1 : 0));
    }

#endif
}
int ffs64Msb(UINT64 i)
{
    union {
        UINT64 qword;
        UINT32 dwords[2];
    } i_u;

    i_u.qword = i;

#if __BYTE_ORDER == __BIG_ENDIAN

    if (i_u.dwords[0])
    {
        return FFS_MSB(i_u.dwords[0]) + 32;
    }
    else
    {
        return FFS_MSB(i_u.dwords[1]);
    }

#else

    if (i_u.dwords[1])
    {
        return FFS_MSB(i_u.dwords[1]) + 32;
    }
    else

    {
        return FFS_MSB(i_u.dwords[0]);
    }

#endif
}

int ffs64Lsb(UINT64 i)
{
    union {
        UINT64 qword;
        UINT32 dwords[2];
    } i_u;

    i_u.qword = i;

#if __BYTE_ORDER == __BIG_ENDIAN

    if (i_u.dwords[1])
    {
        return FFS_LSB(i_u.dwords[1]);
    }
    else
    {
        return FFS_LSB(i_u.dwords[0]) + (i ? 32 : 0);
    }

#else

    if (i_u.dwords[0])
    {
        return FFS_LSB(i_u.dwords[0]);
    }
    else

    {
        return FFS_LSB(i_u.dwords[1]) + (i ? 32 : 0);
    }
#endif
}